package cn.yunyichina.provider.finance.service.impl;

import cn.yunyichina.provider.finance.converter.BoneOrderBoConverter;
import cn.yunyichina.provider.finance.creator.journal.*;
import cn.yunyichina.provider.finance.dao.AccountJournalDao;
import cn.yunyichina.provider.finance.entity.*;
import cn.yunyichina.provider.framework.common.PKGenerator;
import cn.yunyichina.provider.framework.dubbo.service.BaseService;
import cn.yunyichina.provider.framework.dubbo.service.OrderService;
import cn.yunyichina.provider.iface.entity.base.OrderExtVo;
import cn.yunyichina.provider.iface.entity.bone.OrderBoneExtendVo;
import cn.yunyichina.provider.iface.entity.common.Response;
import cn.yunyichina.utils.convert.JsonUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AccountJournalServiceImpl {

	private static final Logger logger = LoggerFactory.getLogger(AccountJournalServiceImpl.class);
	
	@Autowired
	AccountJournalDao accountJournalDao;

	/**
	 * 新增流水收入
	 * @param data
	 * @interfaceName: yyt.finance.account.journal.add
	 * @return
	 */
	public Response addAccountJournal(String data){
		logger.info("AccountJournalServiceImpl.addAccountJournal，入参: " + JSON.toJSONString(data));
		Response response = new Response();
		AccountJournalPo accountJournalPo = JSON.parseObject(data, AccountJournalPo.class);
		if(accountJournalPo != null){
			try {
				accountJournalPo.setId(PKGenerator.generateId());
				accountJournalDao.insert(accountJournalPo);
				response.setResultCodeAndMessage("0","成功");
			} catch (Exception e) {
				logger.error("[AccountJournalServiceImpl.addAccountJournal 新增流水收入异常]" , e);
			}
		}
		return response;
	}


	/**
	 * 修改流水收入
	 * @param data
	 * @interfaceName: yyt.finance.account.journal.update
	 * @return
	 */
	public Response updateAccountJournal(String data){
		logger.info("AccountJournalServiceImpl.updateAccountJournal，入参: " + JSON.toJSONString(data));
		Response response = new Response();
		AccountJournalPo accountJournalPo = JSON.parseObject(data, AccountJournalPo.class);
		if(accountJournalPo != null){
			try {
				accountJournalDao.update(accountJournalPo);
				response.setResultCodeAndMessage("0","成功");
			} catch (Exception e) {
				logger.error("[AccountJournalServiceImpl.updateAccountJournal 修改流水收入异常]" , e);
			}
		}
		return response;
	}


	/**
	 * 根据条件流水收入
	 * @param data
	 * @interfaceName: yyt.finance.account.journal.select
	 * @return
	 */
	public Response selectAccountJournal(String data){
		logger.info("AccountJournalServiceImpl.selectAccountJournal，入参: " + JSON.toJSONString(data));
		Response response = new Response();
		AccountJournalPo accountJournalPo = JsonUtils.parseObject(data, AccountJournalPo.class);
		if(accountJournalPo != null){
			try {
				List<AccountJournalPo> accountJournals = accountJournalDao.select(accountJournalPo);
				response.setResultCodeAndMessageAndResult(Response.SUCCESS_CODE,Response.SUCCESS_MESSAGE , JsonUtils.toJsonString(accountJournals));
			} catch (Exception e) {
				logger.error("[AccountJournalServiceImpl.selectAccountJournal 查询流水收入异常]" , e);
				response.setResultCodeAndMessageAndResult(Response.FAILURE_CODE,Response.FAILURE_MESSAGE , null);
			}
		}
		return response;
	}




	/**
	 * 保存订单对应的流水
	 * 
	 * @param orderNo
	 * @throws Exception
	 */
	public void saveAccountJournalByOrderId(String orderNo) throws Exception {
		logger.info("保存账务流水，入参 orderNo: " + orderNo);
		Map<String, String> data = new HashMap<>();
		data.put("order_no", orderNo);
		Response orderResponse = OrderService.callUnderlineFromInternal("yyt.order.bone.order.get", JSON.toJSONString(data));
		String result = orderResponse.getResult();
		logger.info("查询到骨科订单全部信息: " + result);
		if (StringUtils.isBlank(result)) {
			throw new Exception("未查询到订单信息 orderNo: " + orderNo);
		}
		
		JSONObject resultMap = JSON.parseObject(result);
		BoneOrderBo boneOrderBo = new BoneOrderBoConverter().convert(resultMap);
		logger.info("转换后骨科订单全部信息 boneOrderBo: " + boneOrderBo);
		List<AccountJournalPo> journals = null;
		short orderType = boneOrderBo.getOrderType();
		if (orderType == 91) {
			// 问诊单
			journals = new InquiryOrderJournal(boneOrderBo).createJournal();
		} else if (orderType == 92&&boneOrderBo.getOrderStatus()==97&&"1".equals(boneOrderBo.getManageStatus())) {
			// 手术单（包含押金单和手术单的流水）
			journals = new SurgeryOrderJournal(boneOrderBo).createJournal();
			
			// 手术单对应的押金单
			String depositOrderNo = boneOrderBo.getRelationNo();
			Response depositOrderResponse = OrderService.callUnderlineFromInternal("yyt.order.bone.order.get", "{\"order_no\":\"" + depositOrderNo + "\"}");
			String depositOrderResult = depositOrderResponse.getResult();
			logger.info("手术单 {orderNo: " + orderNo + "} 对应的押金单 {depositOrderNo: " + depositOrderNo + "} 全部信息: " + depositOrderResult);
			if (StringUtils.isNotBlank(depositOrderResult)) {
				JSONObject depositResultMap = JSON.parseObject(depositOrderResult);
				BoneOrderBo depositBoneOrderBo = new BoneOrderBoConverter().convert(depositResultMap);
				logger.info("转换后骨科订单全部信息 depositBoneOrderBo: " + depositBoneOrderBo);
				List<AccountJournalPo> depositJournals = new DepositOrderJournal(depositBoneOrderBo).createJournal();
				journals.addAll(depositJournals);
			}
		} else if (orderType == 93) {
			// 押金单（患者拒绝做手术，不退押金的情形）
			journals = new DepositOrderJournal(boneOrderBo).createJournal();
		} else if(orderType == 94&&boneOrderBo.getOrderStatus()==102&&"1".equals(boneOrderBo.getManageStatus())){
			//面诊单
			journals = new DiagnoseOrderJournal(boneOrderBo).createJournal();
		} else if(orderType == 95&&boneOrderBo.getOrderStatus()==113&&"1".equals(boneOrderBo.getManageStatus())){
			journals = new SeekHelpOrderJournal(boneOrderBo).createJournal();
		}else {
			throw new Exception("无效的订单类型 orderType: " + orderType);
		}
		
		logger.info("待插入账务流水 journals: " + journals);
		accountJournalDao.batchInsert(journals);
	}
	
	/**
	 * 获取用户的流水收入 yyt.finance.account.journal.get
	 * <p>
	 * 获取指定用户每笔订单的收入
	 * @param data
	 * @return
	 */
	public Response getAccountJournal(String data) {
		Response response = new Response();
		try {
			logger.info("[yyt.finance.account.journal.get]获取用户账务流水收入，入参 data: " + data);
			UserJournalDto userJournalDto = JSON.parseObject(data, UserJournalDto.class);
			if (userJournalDto == null || StringUtils.isBlank(userJournalDto.getUser_id()) || StringUtils.isBlank(userJournalDto.getMonth())) {
				logger.error("[yyt.finance.account.journal.get]获取用户账务流水收入失败，缺少参数");
				response.setResultCodeAndMessage("22002", "获取用户的流水收入失败，缺少参数");
				return response;
			}
			
			String beginTime = userJournalDto.getMonth() + "-01 00:00:00";
			String endTime = userJournalDto.getMonth() + "-31 23:59:59";
			List<UserJournalDtoResponse> list = accountJournalDao.getUserJournalByUserId(userJournalDto.getUser_id(), beginTime, endTime);
			if (list == null || list.size() == 0) {
				response.setResultCodeAndMessage("22002", "未查到用户账务流水收入");
			} else {
				//统计净收入、总收入、税费
				int totalAmount = 0;
				int nettedAmount = 0;
				int taxAmount = 0;
				for (UserJournalDtoResponse userJournal : list) {
					String amount = userJournal.getAmount();
					if(StringUtils.isNotBlank(amount)){
						if("2".equals(userJournal.getAmount_direction())){
							totalAmount = totalAmount - Integer.valueOf(amount);
						}else{
							totalAmount += Integer.valueOf(amount);
						}
					}
				}


				//计算税费
				if(totalAmount > 80000 && totalAmount < 400000 && totalAmount > 0){
					taxAmount = computeTax(totalAmount - 80000 , 0.2);
				}else if(totalAmount >= 400000 && totalAmount <= 2000000){
					taxAmount = computeTax(computeTax(totalAmount , 0.8) , 0.2);
				}else if(totalAmount > 2000000 && totalAmount <= 6250000){
					taxAmount = computeTax(computeTax(totalAmount , 0.8) , 0.3) - 200000;
				}else if(totalAmount > 6250000){
					taxAmount = computeTax(computeTax(totalAmount , 0.8) , 0.4) - 700000;
				}else{
					logger.info("总金额小于800 -- totalAmount：" + totalAmount);
					taxAmount = 0;
				}

				//计算净收入
				if(totalAmount > 0){
					nettedAmount = totalAmount - taxAmount;
				}

				Map<String,Object> map = new HashMap<String,Object>();
				map.put("list" , list);
				map.put("totalAmount" , totalAmount);
				map.put("nettedAmount" , nettedAmount);
				map.put("taxAmount" , taxAmount);

				response.setResult(JSON.toJSONString(map));
			}
		} catch (Exception e) {
			logger.error("[yyt.finance.account.journal.get]获取用户的流水收入异常", e);
			response.setResultCodeAndMessage("22002", e.toString());
		}
		
		return response;
	}
	
	/**
	 * 获取手术单收入
	 * yyt.finance.account.journal.order.get
	 * 
	 * @param data order_no
	 * @return
	 */
	public Response getAccountJournalOrder(String data) {
		Response response = new Response();
		try {
			logger.info("[yyt.finance.account.journal.order.get]获取手术单收入，入参 data: " + data);
			UserJournalDto userJournalDto = JSON.parseObject(data, UserJournalDto.class);
			String orderNo = userJournalDto.getOrder_no();
			if (StringUtils.isBlank(orderNo)) {
				logger.error("[yyt.finance.account.journal.order.get]获取手术单收入失败，缺少参数 order_no");
				response.setResultCodeAndMessage("22003", "获取手术单收入，缺少参数 order_no");
				return response;
			}
			
			// 查询order_extend
			Response orderResponse = OrderService.callUnderlineFromInternal(
					"yyt.order.bone.order.get", "{\"order_no\":\"" + orderNo
							+ "\"}");
			String orderResult = orderResponse.getResult();
			logger.info("手术单 {orderNo: " + orderNo + "} 全部信息: " + orderResult);
			if (StringUtils.isBlank(orderResult)) {
				logger.error("[yyt.finance.account.journal.order.get]获取手术单收入失败，查不到订单信息");
				response.setResultCodeAndMessage("22003", "获取手术单收入，查不到订单信息");
				return response;
			}
			
			Map<String, Object> result = new HashMap<>();
			JSONObject orderResultMap = JSON.parseObject(orderResult);
			BoneOrderBo boneOrderBo = new BoneOrderBoConverter().convert(orderResultMap);
			logger.info("转换后骨科订单全部信息 boneOrderBo: " + boneOrderBo);
			
			result.putAll(orderResultMap);
			
			// 推荐人
			IntroducerInfoBo professorIntroducerInfo = new IntroducerInfoBo().initWithUserId(boneOrderBo.getProfessorDoctorId());
			IntroducerInfoBo appointmentIntroducerInfo = new IntroducerInfoBo().initWithUserId(boneOrderBo.getAppointmentDoctorId());

			//设置主治医生一级、二级推荐人名称
			result.put("professor_first_introducer_name" , professorIntroducerInfo.getFirstIntroducerName());
			result.put("professor_second_introducer_name" , professorIntroducerInfo.getSecondIntroducerName());

			//设置专家一级、二级推荐人名称
			result.put("appointment_first_introducer_name" , appointmentIntroducerInfo.getFirstIntroducerName());
			result.put("appointment_second_introducer_name" , appointmentIntroducerInfo.getSecondIntroducerName());

			// 主治一级，二级
			String professorFirstIntroducerId = professorIntroducerInfo.getFirstIntroducerId();
			String professorSecondIntroducerId = professorIntroducerInfo.getSecondIntroducerId();
			// 专家一级，二级
			String appointmentFirstIntroducerId = appointmentIntroducerInfo.getFirstIntroducerId();
			String appointmentSecondIntroducerId = appointmentIntroducerInfo.getSecondIntroducerId();
			
			// 查询该手术单的所有流水（包括押金），为了获取推荐人收入
			List<AccountJournalPo> accountJournals = accountJournalDao.getSurgeryAccountJournal(orderNo);
			for (AccountJournalPo accountJournal : accountJournals) {
				String userId = accountJournal.getUserId();
				if (userId == null) {
					// 平台相关流水
					continue;
				}
				
//				// 主治一级收入
//				if (userId.equals(professorFirstIntroducerId)) {
//					result.put("professor_first_introducer_amount", accountJournal.getAmount());
//				}
//				// 主治二级收入
//				if (userId.equals(professorSecondIntroducerId)) {
//					result.put("professor_second_introducer_amount", accountJournal.getAmount());
//				}
//				// 专家一级收入
//				if (userId.equals(appointmentFirstIntroducerId)) {
//					result.put("appointment_first_introducer_amount", accountJournal.getAmount());
//				}
//				// 专家二级收入
//				if (userId.equals(appointmentSecondIntroducerId)) {
//					result.put("appointment_second_introducer_amount", accountJournal.getAmount());
//				}


				// 主治一级收入
				if (accountJournal.getBusinessType() == 2) {
					result.put("professor_first_introducer_amount", accountJournal.getAmount());
				}
				// 主治二级收入
				if (accountJournal.getBusinessType() == 3) {
					result.put("professor_second_introducer_amount", accountJournal.getAmount());
				}
				// 专家一级收入
				if (accountJournal.getBusinessType() == 5) {
					result.put("appointment_first_introducer_amount", accountJournal.getAmount());
				}
				// 专家二级收入
				if (accountJournal.getBusinessType() == 6) {
					result.put("appointment_second_introducer_amount", accountJournal.getAmount());
				}


			}
			
			if (result.size() == 0) {
				response.setResultCodeAndMessage("22003", "未查到手术单收入");
			} else {
				response.setResult(JSON.toJSONString(result));
			}
			
		} catch (Exception e) {
			logger.error("[yyt.finance.account.journal.order.get]获取手术单收入异常", e);
			response.setResultCodeAndMessage("22003", e.toString());
		}
		
		return response;
	}


	/**
	 * 骨科平台奖励金查询
	 * @param data
	 * @interfaceName: yyt.finance.account.journal.bonus.get
	 * @return
	 */
	public Response getAccountJournalBonus(String data){
		logger.info("AccountJournal.getAccountJournalBonus，入参: " + JSON.toJSONString(data));
		Response response = new Response();
		AccountJournalPo accountJournalPo = JsonUtils.parseObject(data, AccountJournalPo.class);

		if(StringUtils.isBlank(accountJournalPo.getBeginCreatedTime()) || StringUtils.isBlank(accountJournalPo.getEndCreatedTime())){
			response.setResultCodeAndMessage(Response.FAILURE_CODE , "入参 begin_created_time 或 end_created_time为空值");
			return  response;
		}

		if(accountJournalPo != null){
			String beginTime = accountJournalPo.getBeginCreatedTime() + "-01 00:00:00";
			String endTime = accountJournalPo.getEndCreatedTime() + "-31 23:59:59";

			accountJournalPo.setBeginCreatedTime(beginTime);
			accountJournalPo.setEndCreatedTime(endTime);

			try {
				List<AccountJournalPo> accountJournals = accountJournalDao.select(accountJournalPo);
				response.setResultCodeAndMessageAndResult(Response.SUCCESS_CODE,Response.SUCCESS_MESSAGE , JsonUtils.toJsonString(accountJournals));
			} catch (Exception e) {
				logger.error("[AccountJournalServiceImpl.getAccountJournalBonus 奖励金查询异常]" , e);
				response.setResultCodeAndMessageAndResult(Response.FAILURE_CODE,Response.FAILURE_MESSAGE , null);
			}
		}
		return response;
	}



	/**
	 * 确认订单完成（订单取消/流水分成）
	 * @param data
	 * @interfaceName: yyt.finance.account.journal.over.confirm
	 * @return
	 */
	public Response confirmAccountJournalOver(String data){
		logger.info("AccountJournal.confirmAccountJournalOver，入参: " + JSON.toJSONString(data));
		Response response = new Response();
		Map<String , String> map = JSON.parseObject(data, Map.class);

		String depositOrderNo = map.get("deposit_order_no");
		String surgeryOrderNo = map.get("surgery_order_no");
		String orgId = map.get("org_id");
		String userId = map.get("user_id");

		if(StringUtils.isBlank(depositOrderNo) || StringUtils.isBlank(surgeryOrderNo) || StringUtils.isBlank(orgId) || StringUtils.isBlank(userId)){
			response.setResultCodeAndMessage(Response.FAILURE_CODE , "入参 deposit_order_no 或 surgery_order_no 或 org_id 或 user_id为空值");
			return  response;
		}


		//手术单取消订单
		try {
			OrderExtVo orderExtVo = new OrderExtVo();
			orderExtVo.setOrderNo(surgeryOrderNo);
			orderExtVo.setOrgId(orgId);
			Response orderRes = BaseService.callUnderlineFromInternal("yyt.base.order.find", JsonUtils.toJsonString(orderExtVo));
			OrderExtVo orderVo = JsonUtils.parseObject(orderRes.getResult(), OrderExtVo.class);
			orderVo.setOrderStatus((short) 98);
			BaseService.callUnderlineFromInternal("yyt.base.order.update", JsonUtils.toJsonString(orderVo));

			Response boneOrderRes = OrderService.callUnderlineFromInternal("yyt.order.bone.extend.get", JsonUtils.toJsonString(orderExtVo));
			if("0".equals(boneOrderRes.getResultCode())){
				List<OrderBoneExtendVo> orderBoneExtendVos = JsonUtils.parseArray(boneOrderRes.getResult(), OrderBoneExtendVo.class);
				OrderBoneExtendVo boneExtendVo = orderBoneExtendVos.get(0);
				boneExtendVo.setIsAcceptSurgery((short) 0);
				OrderService.callUnderlineFromInternal("yyt.order.bone.extend.by.id.update", JsonUtils.toJsonString(boneExtendVo));
			}

		} catch (Exception e) {
			logger.error("[AccountJournalServiceImpl.confirmAccountJournalOver] 取消订单异常" ,e);
			response.setResultCodeAndMessage(Response.FAILURE_CODE , Response.FAILURE_MESSAGE);
			return response;
		}


		// 押金单流水分成（患者拒绝做手术，不退押金的情形）
		try {
			OrderExtVo orderExtVo = new OrderExtVo();
			orderExtVo.setOrderNo(depositOrderNo);
			orderExtVo.setOrgId(orgId);

			Response orderRes = BaseService.callUnderlineFromInternal("yyt.base.order.find", JsonUtils.toJsonString(orderExtVo));
			OrderExtVo orderVo = JsonUtils.parseObject(orderRes.getResult(), OrderExtVo.class);

			Response boneOrderRes = OrderService.callUnderlineFromInternal("yyt.order.bone.extend.get", JsonUtils.toJsonString(orderExtVo));
			OrderBoneExtendVo boneExtendVo = null;
			if("0".equals(boneOrderRes.getResultCode())){
				List<OrderBoneExtendVo> orderBoneExtendVos = JsonUtils.parseArray(boneOrderRes.getResult(), OrderBoneExtendVo.class);
				boneExtendVo = orderBoneExtendVos.get(0);
			}
			BoneOrderBo boneOrderBo = new BoneOrderBo();
			boneOrderBo.setRelationNo(surgeryOrderNo);
			boneOrderBo.setPlatformId(orderVo.getPlatformId());
			boneOrderBo.setPlatformCode(orderVo.getPlatformCode());
			boneOrderBo.setPlatformName(orderVo.getPlatformName());
			boneOrderBo.setOrderType(orderVo.getOrderType());

			BeanUtils.copyProperties(boneExtendVo , boneOrderBo);
			List<AccountJournalPo> journals = new DepositOrderJournal(boneOrderBo).createJournal();
			logger.info("押金单流水分成 待插入账务流水 journals: " + JsonUtils.toJsonString(journals));
			accountJournalDao.batchInsert(journals);

			response.setResultCodeAndMessage(Response.SUCCESS_CODE , "押金单流水分成完毕");
		} catch (Exception e) {
			logger.error("[AccountJournalServiceImpl.confirmAccountJournalOver] 押金单流水分成异常" ,e);
			response.setResultCodeAndMessage(Response.FAILURE_CODE , Response.FAILURE_MESSAGE);
			return response;
		}

		return response;
	}



	/**
	 * 计算费率
	 * @param amount
	 * @param tax
	 * @return
	 */
	public int computeTax(int amount , double tax){
		BigDecimal bigDecimal = new BigDecimal(amount);
		BigDecimal bigDecimal1 = new BigDecimal(tax);
		return bigDecimal.multiply(bigDecimal1).setScale(0 , BigDecimal.ROUND_HALF_UP).intValue();
	}

	public static void main(String[] args) {
		BigDecimal bigDecimal = new BigDecimal(900);
		BigDecimal bigDecimal1 = new BigDecimal(0.02);

		System.out.println(bigDecimal.multiply(bigDecimal1).setScale(1 , BigDecimal.ROUND_HALF_UP));
	}
}
